﻿using System;
using System.Xml.Serialization;

namespace TeachMe.Application.Configuration
{
    public interface IProperty
    {
        void SetParent(Checkable parent);
    }

    public class Property<T> : IProperty
    {
        public event EventHandler<EventArgs> Changed;

        private T _oldValue;
        private T _value;
        private Checkable _parent;
        private long _timestamp;

        [XmlText]
        public T XmlItem
        {
            get
            {
                return _value;
            }
            set
            {
                _value = value;
            }
        }
        
        [XmlIgnore]
        public T Value
        {
            get
            {
                return _value;
            }
            set
            {
                _value = value;
                Timestamp = DateTime.Now.ToBinary();

                FireChanged();
            }
        }

        [XmlIgnore]
        public long Timestamp
        {
            get { return _timestamp; }
            set { _timestamp = value; }
        }

        private void Register()
        {
            _parent.CheckedOut += delegate
                                               {
                                                   _oldValue = _value;
                                               };
            _parent.Reverted += delegate
                                                {
                                                    _value = _oldValue;

                                                    FireChanged();
                                                };
        }

        public void SetParent(Checkable parent)
        {
            _parent = parent;

            Register();
        }

        private void FireChanged()
        {
            EventHandler<EventArgs> handler = Changed;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }

        protected Property()
        {
            //
        }

        public Property(Checkable parent, T defaultValue)
        {
            _value = defaultValue;
            _parent = parent;

            Register();
        }

        public Property(Checkable parent)
        {
            _parent = parent;

            Register();
        }
    }
}
